1 00:00:01,050 --> 00:00:01,650 Hey there. 2 00:00:01,650 --> 00:00:02,730 Welcome back. 3 00:00:02,730 --> 00:00:08,670 In this lecture we're going to discuss a critical change that has occurred regarding the RRB script 4 00:00:08,670 --> 00:00:11,070 signals in the Roblox game engine. 5 00:00:11,070 --> 00:00:16,620 Recently, Roblox has been changing how callback functions that are connected to events execute when 6 00:00:16,650 --> 00:00:19,410 an event is fired in the original model. 7 00:00:19,410 --> 00:00:25,050 When an event was fired, any callback functions attached to that event would immediately execute afterwards. 8 00:00:25,050 --> 00:00:30,570 For example, if a bindable event was fired, the threat of execution would go and hop in and execute 9 00:00:30,570 --> 00:00:33,360 any callback functions connected to that event. 10 00:00:33,360 --> 00:00:35,940 This is known as an immediate event. 11 00:00:35,940 --> 00:00:42,030 However, Roblox has now changed it to where when an event is fired, instead of going and executing 12 00:00:42,030 --> 00:00:47,250 the callbacks immediately, they instead are placed in a queue based on when the events were fired, 13 00:00:47,250 --> 00:00:53,820 and then these callbacks are executed all at once in order at a slightly later time in a given frame. 14 00:00:53,820 --> 00:00:55,950 This is why they are called deferred events. 15 00:00:56,500 --> 00:01:01,720 By default, all new created games on Roblox are going to have deferred events enabled. 16 00:01:01,750 --> 00:01:07,180 You can change this property in the workspace and this property is called signal behavior. 17 00:01:07,210 --> 00:01:13,780 The default here is still set to immediate, but this is expected to change in February of 2024, when 18 00:01:13,780 --> 00:01:17,260 the default signal behavior is going to be set to deferred. 19 00:01:17,710 --> 00:01:22,600 The reason why this is such a big change is because it may affect event listeners in your game, if 20 00:01:22,600 --> 00:01:24,400 they have been set up incorrectly. 21 00:01:24,400 --> 00:01:28,570 And I'm going to demonstrate to you what may happen in three different scenarios. 22 00:01:29,310 --> 00:01:34,590 Here in this script, I have set up three different examples of how your scripts may execute differently 23 00:01:34,590 --> 00:01:40,080 based on whether you have signal behavior set to deferred or immediate. 24 00:01:40,080 --> 00:01:44,880 In this first example here I have a function connected to the heartbeat event. 25 00:01:44,880 --> 00:01:51,390 And once we hit the 100th frame because we're just going to increment the current frame one by one, 26 00:01:51,390 --> 00:01:57,630 once we hit the 100th frame, we're going to fire a Bindable event, which is Bindable event A, and 27 00:01:57,630 --> 00:02:04,170 then we're going to fire Bindable event B, and then down here I've connected a handler or a callback 28 00:02:04,170 --> 00:02:11,310 function to Bindable event A, and this function is going to connect another callback to Bindable event 29 00:02:11,310 --> 00:02:11,820 B. 30 00:02:12,650 --> 00:02:18,680 Now, how this would work with immediate events is that when we fire Bindable event A, it's going to 31 00:02:18,680 --> 00:02:26,360 immediately hop in and it's going to execute all of the callbacks that are attached to the, um, event 32 00:02:26,540 --> 00:02:29,270 B script signal for Bindable event A. 33 00:02:29,270 --> 00:02:35,870 So that means this function right here is going to be executed immediately once we call the fire function. 34 00:02:35,870 --> 00:02:40,640 And that means we're going to connect another function to bindable event B. 35 00:02:40,640 --> 00:02:44,720 And this function is going to be executed when bindable event B is fired. 36 00:02:45,290 --> 00:02:49,220 So the thread of execution goes in, it fires this event. 37 00:02:49,220 --> 00:02:55,010 Then it goes and executes this function, attaching another function to bindable event B, and then 38 00:02:55,010 --> 00:02:58,610 it comes back into this function connected to heartbeat. 39 00:02:58,610 --> 00:03:01,490 And then it fires bindable Event B's event. 40 00:03:01,490 --> 00:03:07,040 And that means because we have connected this callback right here, this print statement will execute. 41 00:03:07,520 --> 00:03:09,590 Now with deferred events enabled. 42 00:03:09,590 --> 00:03:11,630 This will never execute right here. 43 00:03:11,630 --> 00:03:12,770 And this is why. 44 00:03:12,950 --> 00:03:16,220 So with deferred events it's going to encounter this statement here. 45 00:03:16,220 --> 00:03:18,860 And it's going to fire the event for Bindable a. 46 00:03:18,890 --> 00:03:26,270 However it's not going to go and execute the function connected to Bindable event A instead it's going 47 00:03:26,270 --> 00:03:27,830 to place it in a queue. 48 00:03:27,830 --> 00:03:34,070 Afterward, it's going to immediately fire the event for Bindable B and any functions that are connected 49 00:03:34,070 --> 00:03:37,160 to bindable B are also going to be placed in a queue. 50 00:03:37,190 --> 00:03:46,190 However, because we do not connect any functions to bindable b until the handler for bindable A executes, 51 00:03:46,190 --> 00:03:53,480 that means nothing's going to happen here, because there are no callbacks connected to B, it goes 52 00:03:53,480 --> 00:04:00,290 fires A, it fires B, it places any functions in a queue for A, and then it places any functions in 53 00:04:00,290 --> 00:04:01,130 a queue for b. 54 00:04:01,130 --> 00:04:06,080 Since B will not have any functions in queue, it's just going to place nothing in queue. 55 00:04:06,680 --> 00:04:12,020 And to prove this, we're going to set signal behavior to immediate and we're going to play the game. 56 00:04:12,020 --> 00:04:14,510 We should see this first print statement show up. 57 00:04:14,510 --> 00:04:17,030 And we should also see the second print statement show up. 58 00:04:17,030 --> 00:04:18,740 So if we go and play the game. 59 00:04:19,800 --> 00:04:21,990 And we look inside of the console. 60 00:04:22,260 --> 00:04:23,010 There we go. 61 00:04:23,010 --> 00:04:29,550 Bindable one callback executed at frame 100 and then Bindable two callback executed at frame 100. 62 00:04:30,120 --> 00:04:33,750 As we'd expected with immediate events, Bindable A was fired. 63 00:04:33,780 --> 00:04:38,010 It connected a callback to Bindable B, and then Bindable B was fired. 64 00:04:38,010 --> 00:04:42,660 And because we connected that callback to bindable B, this print statement executed. 65 00:04:42,690 --> 00:04:49,470 Now if we go and switch the signal behavior to deferred, and then we go and playtest the game. 66 00:04:51,840 --> 00:04:57,030 If we look in our console here, as you can see, only that first print statement showed up Bindable 67 00:04:57,030 --> 00:04:59,880 one callback executed at frame 100. 68 00:05:00,450 --> 00:05:06,360 And as I explained earlier, the reason is, is because any callback functions connected to these events 69 00:05:06,360 --> 00:05:07,890 are placed in a queue. 70 00:05:07,920 --> 00:05:14,670 They aren't executed immediately, and because Bindable B does not have any callback functions attached 71 00:05:14,670 --> 00:05:20,790 to it until the callback function for bindable A gets executed, that means nothing is put in queue 72 00:05:20,790 --> 00:05:21,540 right here. 73 00:05:22,630 --> 00:05:25,090 Let's go ahead and take a look at another example here. 74 00:05:25,360 --> 00:05:31,420 In this example we have three Bindable events and Bindable event A, B and C. 75 00:05:31,450 --> 00:05:37,480 They all have a callback connected to them that simply print out when the callback was executed. 76 00:05:37,480 --> 00:05:43,870 However, with Bindable event a Bindable events A is callback goes and fires the event for bindable 77 00:05:43,900 --> 00:05:44,320 c. 78 00:05:44,980 --> 00:05:50,830 This matches pretty closely with the diagram that we took a look at earlier, where if we have the signal 79 00:05:50,830 --> 00:05:57,970 mode set to immediate, what's going to happen is that when we fire Bindable A, it's going to go in, 80 00:05:57,970 --> 00:06:04,120 it's going to execute this callback, and then it's going to see that Bindable C is fired, and then 81 00:06:04,120 --> 00:06:05,440 Bindable C is fired. 82 00:06:05,440 --> 00:06:11,860 It goes in, it checks to see if Bindable C has any callbacks, which it does, and then it executes 83 00:06:11,860 --> 00:06:13,330 Bindable C's callback. 84 00:06:13,330 --> 00:06:16,300 Afterwards it comes back to this area right here. 85 00:06:16,300 --> 00:06:22,840 And then it fires for Bindable B and that's when Bindable B's callback is going to be executed. 86 00:06:22,840 --> 00:06:28,600 So without deferred events this will execute an a, c, b order. 87 00:06:29,110 --> 00:06:35,890 Now if we switched it with deferred events what's going to happen instead is that Bindable A is going 88 00:06:35,890 --> 00:06:36,820 to fire. 89 00:06:37,500 --> 00:06:44,580 It's going to put this callback in a queue, and it's not going to fire Bindable C until that queue 90 00:06:44,580 --> 00:06:47,730 is reached and it starts executing all of the functions in the queue. 91 00:06:48,240 --> 00:06:53,820 So all the callbacks for bindable A are queued, and then it goes and queues all of the callbacks for 92 00:06:53,820 --> 00:06:54,630 bindable b. 93 00:06:55,290 --> 00:07:01,140 Now once that queue is reached, what's going to happen is the first callback is going to be executed, 94 00:07:01,650 --> 00:07:07,200 and then it's going to fire the event for Bindable C however, it's not going to go and immediately 95 00:07:07,200 --> 00:07:09,180 execute the callback for Bindable C. 96 00:07:09,210 --> 00:07:15,060 Instead, it's going to put the callback for Bindable c in the queue, and since the queue is going 97 00:07:15,060 --> 00:07:21,060 to be in order, that means the callback for bindable C is not going to be executed until after the 98 00:07:21,060 --> 00:07:23,520 callback for Bindable B is executed. 99 00:07:23,520 --> 00:07:28,590 So that means with deferred events, this is going to execute an a, b, c order. 100 00:07:28,590 --> 00:07:34,410 And we can prove that with signal behavior set to deferred and we go and playtest our game. 101 00:07:34,440 --> 00:07:38,070 Let me actually go and comment this out first. 102 00:07:38,670 --> 00:07:40,440 And then we can go play test our game. 103 00:07:40,800 --> 00:07:49,560 If we look Bindable a, B then C executed with signal behavior set to deferred just as we would expect. 104 00:07:50,530 --> 00:07:55,720 But if we go back in the workspace and then we set signal behavior back to immediate. 105 00:07:56,330 --> 00:07:58,490 And then we go and play test our game. 106 00:07:59,750 --> 00:08:07,190 As you can see now, it's set in a C be order because the callback for Bindable A was immediately executed, 107 00:08:07,190 --> 00:08:12,440 which fired the event for Bindable C, that means Bindable C's callback was immediately executed, and 108 00:08:12,440 --> 00:08:15,200 then finally Bindable B's callback was executed. 109 00:08:15,830 --> 00:08:16,520 Okay. 110 00:08:16,520 --> 00:08:20,960 In this final example we're going to take a look at here is we're going to be listening to the character 111 00:08:20,960 --> 00:08:21,740 removing event. 112 00:08:21,740 --> 00:08:26,570 So this gets fired before the character is removed inside of the callback function. 113 00:08:26,570 --> 00:08:28,040 For the character removing event. 114 00:08:28,040 --> 00:08:33,770 We're also attaching another callback function to the ancestry changed event, and we're going to print 115 00:08:33,770 --> 00:08:37,190 when the parent of the character is set to nil. 116 00:08:37,310 --> 00:08:42,950 Now with the media events, all of this should print inside of the console, but with deferred events, 117 00:08:42,950 --> 00:08:49,520 this function right here should never execute for the exact same reason that we observed with the previous 118 00:08:49,520 --> 00:08:50,600 two examples. 119 00:08:50,600 --> 00:08:56,900 Because you think of it internally when the character removing event is going to be fired, any of those 120 00:08:56,900 --> 00:09:01,490 functions connected to it are going to be queued, and then the ancestry changed event is also going 121 00:09:01,490 --> 00:09:02,990 to be fired for the character. 122 00:09:02,990 --> 00:09:06,410 And any of those functions are also going to be placed in a queue. 123 00:09:06,440 --> 00:09:13,280 However, since we're not going to have any functions connected to the ancestry changed event because 124 00:09:13,280 --> 00:09:18,560 they only happen within this callback, that means this function right here should never execute. 125 00:09:19,260 --> 00:09:26,310 So if we go and playtest the game and we have the signal behavior set to immediate, then we should 126 00:09:26,310 --> 00:09:29,460 expect both of those print statements to appear in the console. 127 00:09:29,790 --> 00:09:35,760 So if I go and reset my character and then wait for the character to get removed, there we go. 128 00:09:35,760 --> 00:09:39,060 It says character is removing and then the parent is a nil. 129 00:09:39,540 --> 00:09:47,760 However, if we go and now set the signal behavior to deferred and then we play tested our game. 130 00:09:48,850 --> 00:09:50,860 And then I reset my character. 131 00:09:54,330 --> 00:10:00,390 As you can see now, only character is removing got printed and the parent print statement did not get 132 00:10:00,390 --> 00:10:02,160 printed inside of our console. 133 00:10:02,750 --> 00:10:08,120 I hope this lecture helped clear up any confusion regarding deferred events and immediate events. 134 00:10:08,120 --> 00:10:12,800 Since deferred events are the future for the Roblox game engine, it's important to know how events 135 00:10:12,800 --> 00:10:16,640 are handled to prevent any problems from occurring in your scripts. 136 00:10:16,670 --> 00:10:19,310 Thanks for watching and I'll see you in the next lecture.